package com.ai.service.security.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.ai.common.CommonResponse;
import com.ai.common.constant.RedisConstants;
import com.ai.common.constant.enumP.PermissionType;
import com.ai.common.constant.enumP.RoleTypeEnum;
import com.ai.entity.BasePage;
import com.ai.entity.made.RegionBase;
import com.ai.entity.made.camera.CameraVO;
import com.ai.entity.security.*;
import com.ai.entity.security.page.SysRolePage;
import com.ai.mapper.security.SysRoleMapper;
import com.ai.model.param.BindingPermissionParam;
import com.ai.model.param.SysRoleParam;
import com.ai.model.vo.SysRoleVo;
import com.ai.service.made.IRegionBaseService;
import com.ai.service.security.*;
import com.ai.util.SecurityUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户角色表 服务实现类
 * </p>
 *
 * @author chen
 * @since 2023-04-04 19:46:07
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {

    @Resource
    private ISysPermissionService iSysPermissionService;

    @Resource
    private ISysRolePermissionRelationService iSysRolePermissionRelationService;

    @Resource
    private ISysUserRoleRelationService iSysUserRoleRelationService;

    @Resource
    private SysRoleServiceImpl sysRoleService;


    @Resource
    private IRegionBaseService iRegionBaseService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private ISysUserService iSysUserService;


    /**
     * 新增角色
     * @param sysRoleParam
     * @return
     */
    @Override
    @Transactional
    public CommonResponse<String> add(SysRoleParam sysRoleParam) {
        SysRole sysRole = new SysRole();
        //判断当前新增的角色名是否已经存在
        List<SysRole> roleList = this.list();
        List<String> roleNameList =
                roleList.stream().map(SysRole::getRoleName).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(roleNameList) && roleNameList.contains(sysRoleParam.getRoleName())){
            return  CommonResponse.error("当前角色名已存在,不可重复添加");
        }

        sysRole.setRoleName(sysRoleParam.getRoleName());
        sysRole.setRoleDescription(sysRoleParam.getRoleDescription());
        sysRole.setRoleType(RoleTypeEnum.ROLE_SYS.getRoleType());
        sysRole.setRegionBaseId(SecurityUtils.getLoginRegionBaseId());
        //新增角色
        this.save(sysRole);

        //新增角色权限关系
        SysRole role = this.getOne(new QueryWrapper<SysRole>()
                .eq("role_name", sysRoleParam.getRoleName()));
        BindingPermissionParam permissionParam = new BindingPermissionParam();
        permissionParam.setRoleId(String.valueOf(role.getId()));
        permissionParam.setPermissionIds(sysRoleParam.getPermissionIds());
        CommonResponse<String> stringCommonResponse = sysRoleService.bindingPermission(permissionParam);
        if (stringCommonResponse.getCode() != 200){
            return stringCommonResponse;
        }

        return CommonResponse.ok("新增成功");
    }

    /**
     * 更新角色信息
     * @param sysRoleParam
     * @return
     */
    @Override
    @Transactional
    public CommonResponse<String> updateByParam(SysRoleParam sysRoleParam) {

        //判断当前新增的角色名是否已经存在
        List<SysRole> roleList = this.list();
        List<String> roleNameList =
                roleList.stream().filter(sysRole -> {
                    return !(sysRoleParam.getId().equals(sysRole.getId().toString()));
                }).map(SysRole::getRoleName).collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(roleNameList) && roleNameList.contains(sysRoleParam.getRoleName())){
            return  CommonResponse.error("当前角色名已存在,不可重复添加");
        }
        //更新角色信息
        SysRole sysRole = new SysRole();
        sysRole.setId(Integer.valueOf(sysRoleParam.getId()));
        sysRole.setRoleName(sysRoleParam.getRoleName());
        sysRole.setRoleDescription(sysRoleParam.getRoleDescription());
        this.updateById(sysRole);

        //更新角色权限之间的关系

        BindingPermissionParam permissionParam = new BindingPermissionParam();
        permissionParam.setRoleId(sysRoleParam.getId());
        permissionParam.setPermissionIds(sysRoleParam.getPermissionIds());

        CommonResponse<String> stringCommonResponse = sysRoleService.bindingPermission(permissionParam);

        if (stringCommonResponse.getCode() != 200){
            return stringCommonResponse;
        }

        List<SysUserRoleRelation> sysUserRoleRelations = iSysUserRoleRelationService.list(new QueryWrapper<SysUserRoleRelation>()
                .eq("role_id", sysRole.getId()));

        if (!CollectionUtils.isEmpty(sysUserRoleRelations)){
            //删除当前角色对应的所有用户，并清空redis中缓存的信息
            for (SysUserRoleRelation sysUserRoleRelation : sysUserRoleRelations) {
                log.debug("----------------------  清除redis缓存中的用户信息  ----------------------");
                log.debug("----------------------  用户id"+sysUserRoleRelation.getUserId()+"    ----------------------");
                stringRedisTemplate.delete(RedisConstants.LOGIN_USER_INFO +sysUserRoleRelation.getUserId().toString());
            }
        }
        return CommonResponse.ok("更新成功");
    }

    /**
     * 给当前用户绑定权限信息
     * @param permissionParam
     * @return
     */
    @Override
    @Transactional
    public CommonResponse<String> bindingPermission(BindingPermissionParam permissionParam) {

//        查看当前角色是否合法
        SysRole sysRole = this.getOne(new QueryWrapper<SysRole>()
                .eq("id", permissionParam.getRoleId()));
        if (null == sysRole){
            return CommonResponse.error("当前角色不存在,不可进行赋权操作");
        }

        if (null== permissionParam.getPermissionIds() ||CollectionUtils.isEmpty(permissionParam.getPermissionIds())){
            //当前角色所拥有的权限全部清空
            boolean remove = iSysRolePermissionRelationService.remove(new QueryWrapper<SysRolePermissionRelation>()
                    .eq("role_id", permissionParam.getRoleId()));
            return CommonResponse.ok("操作完成");
        }

//        查看所绑定的权限是否合法
        List<SysPermission> list = iSysPermissionService.list(new QueryWrapper<SysPermission>()
                .in("id", permissionParam.getPermissionIds()));

        if (permissionParam.getPermissionIds().size() != list.size()){
            //查询到的权限个数和前端所想要操作的权限数对不上，说明有非法操作
            throw new RuntimeException("请选择合法的权限进行绑定");
        }

        //进行合法操作

        //先删除当前角色所有权限
        boolean role_id = iSysRolePermissionRelationService.remove(new QueryWrapper<SysRolePermissionRelation>()
                .eq("role_id", permissionParam.getRoleId()));

        for (String permissionId : permissionParam.getPermissionIds()) {
            SysRolePermissionRelation sysRolePermissionRelation = new SysRolePermissionRelation();

            sysRolePermissionRelation.setRoleId(Integer.valueOf(permissionParam.getRoleId()));
            sysRolePermissionRelation.setPermissionId(Integer.valueOf(permissionId));
            iSysRolePermissionRelationService.save(sysRolePermissionRelation);
        }
        return CommonResponse.ok("操作成功");
    }

    /**
     * 删除角色   同时删除对应的权限关系
     * @param id
     * @return
     */
    @Override
    @Transactional
    public CommonResponse<String> removeRoleById(Integer id) {
        //删除当前角色对应的redis缓存
        List<SysUserRoleRelation> sysUserRoleRelations = iSysUserRoleRelationService.list(new QueryWrapper<SysUserRoleRelation>()
                .eq("role_id", id));
        if (!CollectionUtils.isEmpty(sysUserRoleRelations)){
            //存在用户绑定当前角色，删除失败
            return CommonResponse.error("存在用户绑定当前角色，删除失败");
            //删除当前角色对应的所有用户，并清空redis中缓存的信息
//            for (SysUserRoleRelation sysUserRoleRelation : sysUserRoleRelations) {
//                log.debug("----------------------  清除redis缓存中的用户信息  ----------------------");
//                log.debug("----------------------  用户id"+sysUserRoleRelation.getUserId()+"    ----------------------");
//                stringRedisTemplate.delete(RedisConstants.LOGIN_USER_INFO +sysUserRoleRelation.getUserId().toString());
//            }
        }

        //删除角色
        this.removeById(id);

        //删除角色权限关系
        boolean role_id = iSysRolePermissionRelationService.remove(new QueryWrapper<SysRolePermissionRelation>()
                .eq("role_id", id));
        // 删除用户角色之间关系
        boolean role_id1 = iSysUserRoleRelationService.remove(new QueryWrapper<SysUserRoleRelation>()
                .eq("role_id", id));

//         : 2023-06-15 给没有角色的用户添加新的角色
        
        
        return CommonResponse.ok("删除成功");
    }

    @Override
    public List<SysRole> getUserBindRole(Integer userId) {

        List<SysRole> roleList = baseMapper.getBindRoleList(userId);

        if (!CollectionUtils.isEmpty(roleList)){
            if (roleList.size() > 1 ){
                Collections.sort(roleList, new Comparator<SysRole>() {
                    @Override
                    public int compare(SysRole o1, SysRole o2) {
                        return o1.getRoleType().compareTo(o2.getRoleType());
                    }
                });
                return roleList;
            } else if  (roleList.size() == 1 && !roleList.get(0).getRoleType().equals(RoleTypeEnum.ROLE_SYS.getRoleType())){
                // 如果当前用户只绑定了角色，则只能是系统角色   -------创建本身角色
                throw new RuntimeException("当前登录用户禁止登陆，请联系管理");
            }else {
                //新建并绑定当前用户本身角色
                SysUser sysUser = iSysUserService.getById(userId);
                SysUserRoleRelation sysUserRoleRelation = iSysUserRoleRelationService.saveItselfRelation(sysUser);
                SysRole sysRole = this.getById(sysUserRoleRelation.getRoleId());
                roleList.add(sysRole);
                return roleList;
            }
        }else {
            //当前用户没有绑定角色，禁止登录
            throw new RuntimeException("当前登录用户禁止登陆，请联系管理");
        }

    }

    @Override
    public SysRole saveItselfRole(SysUser sysUser) {


        SysRole sysRole = new SysRole();
        sysRole.setRoleName(sysUser.getUserName());
        sysRole.setRoleType(RoleTypeEnum.ROLE_USER.getRoleType());
        sysRole.setRoleDescription("用户本身角色，用于拓展功能");

        this.save(sysRole);

        return sysRole;
    }

    @Override
    public List<SysRole> getUserSelfRole() {
        QueryWrapper<SysRole> queryWrapper = new QueryWrapper<SysRole>().eq("role_type", RoleTypeEnum.ROLE_USER.getRoleType());
        List<SysRole> sysRoleList = this.list(queryWrapper);
        return sysRoleList;
    }

    @Override
    public IPage pageList(SysRolePage page) {
        IPage<SysRoleVo> voIPage = new BasePage<>();
        // 根据创建时间排序
        List<String> belowRegionIdList = iRegionBaseService.getBelowRegionIdList(SecurityUtils.getLoginRegionBaseId());
        page.setRegionBaseIdList(belowRegionIdList);

        QueryWrapper<SysRole> queryWrapper = page.getQuery(new QueryWrapper<>());
        IPage<SysRole> iPage = sysRoleService.page(page, queryWrapper);
        List<SysRole> iPageRecords = iPage.getRecords();
        if (CollectionUtil.isEmpty(iPageRecords)){
            return iPage;
        }

        List<SysRoleVo> roleVoList = iPageRecords.stream().map(sysRole -> {
            SysRoleVo sysRoleVo = new SysRoleVo();
            BeanUtils.copyProperties(sysRole, sysRoleVo);
            RegionBase regionBase = iRegionBaseService.getById(sysRole.getRegionBaseId());
            sysRoleVo.setRegionName(regionBase.getRegionName());
            return sysRoleVo;
        }).sorted(Comparator.comparing(SysRoleVo::getRegionBaseId)).collect(Collectors.toList());

        BeanUtils.copyProperties(iPage,voIPage);
        voIPage.setRecords(roleVoList);

        return voIPage;
    }
}
